﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Controls;
using YArchitech.Revit.RevitExtension;
using YJKTextDimension.Utility;

namespace YJKTextDimension.DimCreator
{
	internal class CombinedDimension
	{
		public CombinedDimension(Autodesk.Revit.DB.Document doc, UV max, UV min)
		{
			this.doc = doc;
			this.max = max;
			this.min = min;
		}

		public bool Combined()
		{
			bool result = false;
			Transaction transaction = null;
			try
			{
				transaction = new Transaction(this.doc, "Combined");
				transaction.Start();
				List<Dimension> dimensionsByPickBox = this.GetDimensionsByPickBox();
				if (dimensionsByPickBox.Count > 1)
				{
					YJKMessageBox.Show("请选择一道标注上的不同区间");
					return result;
				}
				List<Dimension> list = new List<Dimension>();
				foreach (Dimension dimension in dimensionsByPickBox)
				{
					bool flag = this.Combined(dimension);
					if (flag)
					{
						list.Add(dimension);
					}
				}
				foreach (Dimension dimension2 in list)
				{
					this.doc.Delete(dimension2.Id);
				}
				result = true;
				transaction.Commit();
			}
			finally
			{
				if (transaction != null)
				{
					TransactionStatus status = transaction.GetStatus();
					if (status != (TransactionStatus)3)
					{
						transaction.RollBack();
					}
				}
			}
			return result;
		}

		private bool Combined(Dimension dim)
		{
			bool result = false;
			Dimension dimension = null;
			string dimensionShareParam = this.GetDimensionShareParam(dim);
			ReferenceArray referenceArray = new ReferenceArray();
			new List<Reference>();
			Line line = dim.Curve as Line;
			Line line2 = Line.CreateBound(line.Origin, line.Origin + line.Direction * 100.0);
			DimensionType dimensionType = this.doc.GetElement(dim.GetTypeId()) as DimensionType;
			List<SegmentReferenceRelation> segmentReferenceRelation = this.GetSegmentReferenceRelation(dim);
			SegmentReferenceRelation segmentReferenceRelation2 = segmentReferenceRelation.First<SegmentReferenceRelation>();
			SegmentReferenceRelation segmentReferenceRelation3 = segmentReferenceRelation.Last<SegmentReferenceRelation>();
			List<XYZ> dimMarkPoints = segmentReferenceRelation2.DimMarkPoints;
			XYZ pt = dimMarkPoints[0];
			bool flag = this.IsSelected(pt);
			dimMarkPoints = segmentReferenceRelation3.DimMarkPoints;
			pt = dimMarkPoints[1];
			bool flag2 = this.IsSelected(pt);
			if ((flag && flag2) || segmentReferenceRelation.Count == 1)
			{
				referenceArray.Append(segmentReferenceRelation2.DimReferences[0]);
				referenceArray.Append(segmentReferenceRelation3.DimReferences[1]);
				ReferenceArray referenceArray2 = new ReferenceArray();
				foreach (object obj in referenceArray)
				{
					Reference refElem = (Reference)obj;
					referenceArray2.Append(DimUtility.ConvertDimReference(this.doc, refElem));
				}
				dimension = this.doc.Create.NewDimension(this.doc.ActiveView, line2, referenceArray2, dimensionType);
				if (!string.IsNullOrEmpty(dimensionShareParam))
				{
					DimPublicFunc.SetDimFlag(dimension, dimensionShareParam);
				}
				RevitDimensionExtension.ResetDimTextPos(dimension);
			}
			else
			{
				if (segmentReferenceRelation.Count > 1)
				{
					List<XYZ> list = new List<XYZ>();
					foreach (SegmentReferenceRelation segmentReferenceRelation4 in segmentReferenceRelation)
					{
						dimMarkPoints = segmentReferenceRelation4.DimMarkPoints;
						for (int i = 0; i < dimMarkPoints.Count; i++)
						{
							if (!this.IsSelected(dimMarkPoints[i]) && !list.Contains(dimMarkPoints[i], new XYZEqualityComparer()))
							{
								list.Add(dimMarkPoints[i]);
								referenceArray.Append(segmentReferenceRelation4.DimReferences[i]);
							}
						}
					}
				}
				if (referenceArray.Size > 1)
				{
					ReferenceArray referenceArray3 = new ReferenceArray();
					foreach (object obj2 in referenceArray)
					{
						Reference refElem2 = (Reference)obj2;
						Reference reference = DimUtility.ConvertDimReference(this.doc, refElem2);
						referenceArray3.Append(reference);
					}
					dimension = this.doc.Create.NewDimension(this.doc.ActiveView, line2, referenceArray3, dimensionType);
					if (!string.IsNullOrEmpty(dimensionShareParam))
					{
						DimPublicFunc.SetDimFlag(dimension, dimensionShareParam);
					}
					RevitDimensionExtension.ResetDimTextPos(dimension);
				}
			}
			if (dimension != null)
			{
				result = true;
			}
			return result;
		}

		private string GetDimensionShareParam(Dimension sourceDim)
		{
			string result = null;
			string dimFlag = DimPublicFunc.GetDimFlag(sourceDim);
			if (!string.IsNullOrEmpty(dimFlag))
			{
				return dimFlag;
			}
			return result;
		}

		private List<Dimension> GetDimensionsByPickBox()
		{
			List<Dimension> list = new List<Dimension>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.doc, this.doc.ActiveView.Id);
			List<Dimension> list2 = (from d in filteredElementCollector.OfClass(typeof(Dimension)).OfCategory(BuiltInCategory.OST_Dimensions)
			select d as Dimension).ToList<Dimension>();
			if (list2 == null || list2.Count < 1)
			{
				return list;
			}
			foreach (Dimension dimension in list2)
			{
				if (dimension.DimensionShape == null && dimension.References != null && dimension.References.Size >= 1 && this.IsSelected(dimension))
				{
					list.Add(dimension);
				}
			}
			return list;
		}

		private bool IsSelected(Dimension dim)
		{
			bool flag = false;
			List<XYZ> dimensionMarkPoint = this.GetDimensionMarkPoint(dim);
			foreach (XYZ pt in dimensionMarkPoint)
			{
				flag = this.IsSelected(pt);
				if (flag)
				{
					break;
				}
			}
			return flag;
		}

		private bool IsSelected(XYZ pt)
		{
			bool result = false;
			if (pt.X >= this.min.U && pt.X <= this.max.U && pt.Y >= this.min.V && pt.Y <= this.max.V)
			{
				result = true;
			}
			return result;
		}

		private List<XYZ> GetDimensionMarkPoint(Dimension dim)
		{
			List<XYZ> list = new List<XYZ>();
			Line line = dim.Curve as Line;
			DimensionSegmentArray segments = dim.Segments;
			if (segments.Size == 0)
			{
				XYZ origin = dim.Origin;
				double? value = dim.Value;
				double num = (value != null) ? value.GetValueOrDefault() : -1.0;
				XYZ xyz = origin + line.Direction * (num / 2.0);
				list.Add(xyz);
				xyz = origin + -line.Direction * (num / 2.0);
				list.Add(xyz);
			}
			else
			{
				foreach (object obj in segments)
				{
					DimensionSegment dimensionSegment = (DimensionSegment)obj;
					XYZ origin2 = dimensionSegment.Origin;
					double? value2 = dimensionSegment.Value;
					double num2 = (value2 != null) ? value2.GetValueOrDefault() : -1.0;
					if (num2 != -1.0)
					{
						if (num2 == 0.0)
						{
							if (!list.Contains(origin2, new XYZEqualityComparer()))
							{
								list.Add(origin2);
							}
						}
						else
						{
							XYZ xyz = origin2 + line.Direction * (num2 / 2.0);
							if (!list.Contains(xyz, new XYZEqualityComparer()))
							{
								list.Add(xyz);
							}
							xyz = origin2 + -line.Direction * (num2 / 2.0);
							if (!list.Contains(xyz, new XYZEqualityComparer()))
							{
								list.Add(xyz);
							}
						}
					}
				}
			}
			return list;
		}

		private List<XYZ> GetGetDimensionMarkPoint(XYZ direction, DimensionSegment segment)
		{
			List<XYZ> list = new List<XYZ>();
			XYZ origin = segment.Origin;
			double? value = segment.Value;
			double num = (value != null) ? value.GetValueOrDefault() : -1.0;
			if (num == 0.0)
			{
				list.Add(origin);
				list.Add(origin);
			}
			else
			{
				XYZ item = origin + -direction * (num / 2.0);
				list.Add(item);
				item = origin + direction * (num / 2.0);
				list.Add(item);
			}
			return list;
		}

		private List<SegmentReferenceRelation> GetSegmentReferenceRelation(Dimension dim)
		{
			List<SegmentReferenceRelation> list = new List<SegmentReferenceRelation>();
			Curve curve = dim.Curve;
			ReferenceArray references = dim.References;
			DimensionSegmentArray segments = dim.Segments;
			XYZ origin = segments.get_Item(0).Origin;
			XYZ origin2 = segments.get_Item(segments.Size - 1).Origin;
			XYZ direction = (origin2 - origin).Normalize();
			for (int i = 0; i < segments.Size; i++)
			{
				DimensionSegment dimensionSegment = segments.get_Item(i);
				List<Reference> list2 = new List<Reference>();
				list2.Add(references.get_Item(i));
				list2.Add(references.get_Item(i+1));
				List<XYZ> getDimensionMarkPoint = this.GetGetDimensionMarkPoint(direction, dimensionSegment);
				list.Add(new SegmentReferenceRelation
				{
					Index = i,
					DimSegment = dimensionSegment,
					DimReferences = list2,
					DimMarkPoints = getDimensionMarkPoint
				});
			}
			return list;
		}

		private Document doc;

		private UV max;

		private UV min;
	}
}
